#!/bin/bash
expect() {
  actual="`./undname $1`"
  [[ "$actual" == "$2" ]] || { echo "$2 expected, but got $actual"; exit 1; }
}

expect '?x@@3HA' 'int x'
expect '?x@@3PEAHEA' 'int*x'
expect '?x@@3PEAPEAHEA' 'int**x'
expect '?x@@3PEAY02HEA' 'int(*x)[3]'
expect '?x@@3PEAY124HEA' 'int(*x)[3][5]'
expect '?x@@3PEAY02$$CBHEA' 'int const(*x)[3]'
expect '?x@@3PEAEEA' 'unsigned char*x'
expect '?x@@3PEAY1NKM@5HEA' 'int(*x)[3500][6]'
expect '?x@@YAXMH@Z' 'void x(float,int)'
expect '?x@@YAXMH@Z' 'void x(float,int)'
expect '?x@@3P6AHMNH@ZEA' 'int(*x)(float,double,int)'
expect '?x@@3P6AHP6AHM@ZN@ZEA' 'int(*x)(int(*)(float),double)'
expect '?x@@3P6AHP6AHM@Z0@ZEA' 'int(*x)(int(*)(float),int(*)(float))'

expect '?x@ns@@3HA' 'int ns::x'

# Microsoft's undname returns "int const * const x" for this symbol.
# I believe it's their bug.
expect '?x@@3PEBHEB' 'int const*x'

expect '?x@@3QEAHEB' 'int*const x'
expect '?x@@3QEBHEB' 'int const*const x'

expect '?x@@3AEBHEB' 'int const&x'

expect '?x@@3PEAUty@@EA' 'struct ty*x'
expect '?x@@3PEATty@@EA' 'union ty*x'
expect '?x@@3PEAUty@@EA' 'struct ty*x'
expect '?x@@3PEAW4ty@@EA' 'enum ty*x'
expect '?x@@3PEAVty@@EA' 'class ty*x'

expect '?x@@3PEAV?$tmpl@H@@EA' 'class tmpl<int>*x'
expect '?x@@3PEAU?$tmpl@H@@EA' 'struct tmpl<int>*x'
expect '?x@@3PEAT?$tmpl@H@@EA' 'union tmpl<int>*x'
expect '?instance@@3Vklass@@A' 'class klass instance'
expect '?instance$initializer$@@3P6AXXZEA' 'void(*instance$initializer$)(void)'
expect '??0klass@@QEAA@XZ' 'klass::klass(void)'
expect '??1klass@@QEAA@XZ' 'klass::~klass(void)'
expect '?x@@YAHPEAVklass@@AEAV1@@Z' 'int x(class klass*,class klass&)'
expect '?x@ns@@3PEAV?$klass@HH@1@EA' 'class ns::klass<int,int>*ns::x'
expect '?fn@?$klass@H@ns@@QEBAIXZ' 'unsigned int ns::klass<int>::fn(void)const'

expect '??4klass@@QEAAAEBV0@AEBV0@@Z' 'class klass const&klass::operator=(class klass const&)'
expect '??7klass@@QEAA_NXZ' 'bool klass::operator!(void)'
expect '??8klass@@QEAA_NAEBV0@@Z' 'bool klass::operator==(class klass const&)'
expect '??9klass@@QEAA_NAEBV0@@Z' 'bool klass::operator!=(class klass const&)'
expect '??Aklass@@QEAAH_K@Z' 'int klass::operator[](uint64_t)'
expect '??Cklass@@QEAAHXZ' 'int klass::operator->(void)'
expect '??Dklass@@QEAAHXZ' 'int klass::operator*(void)'
expect '??Eklass@@QEAAHXZ' 'int klass::operator++(void)'
expect '??Eklass@@QEAAHH@Z' 'int klass::operator++(int)'
expect '??Fklass@@QEAAHXZ' 'int klass::operator--(void)'
expect '??Fklass@@QEAAHH@Z' 'int klass::operator--(int)'
expect '??Hklass@@QEAAHH@Z' 'int klass::operator+(int)'
expect '??Gklass@@QEAAHH@Z' 'int klass::operator-(int)'
expect '??Iklass@@QEAAHH@Z' 'int klass::operator&(int)'
expect '??Jklass@@QEAAHH@Z' 'int klass::operator->*(int)'
expect '??Kklass@@QEAAHH@Z' 'int klass::operator/(int)'
expect '??Mklass@@QEAAHH@Z' 'int klass::operator<(int)'
expect '??Nklass@@QEAAHH@Z' 'int klass::operator<=(int)'
expect '??Oklass@@QEAAHH@Z' 'int klass::operator>(int)'
expect '??Pklass@@QEAAHH@Z' 'int klass::operator>=(int)'
expect '??Qklass@@QEAAHH@Z' 'int klass::operator,(int)'
expect '??Rklass@@QEAAHH@Z' 'int klass::operator()(int)'
expect '??Sklass@@QEAAHXZ' 'int klass::operator~(void)'
expect '??Tklass@@QEAAHH@Z' 'int klass::operator^(int)'
expect '??Uklass@@QEAAHH@Z' 'int klass::operator|(int)'
expect '??Vklass@@QEAAHH@Z' 'int klass::operator&&(int)'
expect '??Wklass@@QEAAHH@Z' 'int klass::operator||(int)'
expect '??Xklass@@QEAAHH@Z' 'int klass::operator*=(int)'
expect '??Yklass@@QEAAHH@Z' 'int klass::operator+=(int)'
expect '??Zklass@@QEAAHH@Z' 'int klass::operator-=(int)'
expect '??_0klass@@QEAAHH@Z' 'int klass::operator/=(int)'
expect '??_1klass@@QEAAHH@Z' 'int klass::operator%=(int)'
expect '??_2klass@@QEAAHH@Z' 'int klass::operator>>=(int)'
expect '??_3klass@@QEAAHH@Z' 'int klass::operator<<=(int)'
expect '??_6klass@@QEAAHH@Z' 'int klass::operator^=(int)'
expect '??6@YAAEBVklass@@AEBV0@H@Z' 'class klass const&operator<<(class klass const&,int)'
expect '??5@YAAEBVklass@@AEBV0@_K@Z' 'class klass const&operator>>(class klass const&,uint64_t)'
expect '??2@YAPEAX_KAEAVklass@@@Z' 'void*operator new(uint64_t,class klass&)'
expect '??_U@YAPEAX_KAEAVklass@@@Z' 'void*operator new[](uint64_t,class klass&)'
expect '??3@YAXPEAXAEAVklass@@@Z' 'void operator delete(void*,class klass&)'
expect '??_V@YAXPEAXAEAVklass@@@Z' 'void operator delete[](void*,class klass&)'

echo OK
